パソコン活用研究ラピュタへの道(アセンブラ、DOS、Windows、旧型PCの活用研究)
時計の作成
1 プログラムの概要
それでは、今回は時計を作成してみます。
MS−DOSコマンドでいうと、TIME や DATE
のようなものです。
日付、時刻の表示と設定変更ができます。
(1) 使用するファンクションコール
日付の表示、時刻の表示、はMS−DOSファンクションコールの
2AH,2CH
日付の設定、時刻の設定は、2BH,2DHです
(2) プログラムの主要部分の概説
表示の方は、16進数バイナリデータ −−>10進数に変換
−−> アスキーコードに変換して表示
設定の方は、アスキーコードの入力データ
(10進数として)−−>
16進数バイナリデータに変換
という作業がメインです。
コードの80%は、この作業の記述です。
上述の変換に関しては、DEBUGで機械語作制その2、アセンブラでCOMファイル作制 で多少説明して
いますので、なんのこっちゃ?という方は参考にして下さい。
BASICあたりで記述すると、 print time$
程度の単純なプログラムですが、アセンブラで記述すると
上述のような変換のためのコードをえんえんと書くはめになります。とりあえず、コードを見てください。
こんな単純なプログラムにこなんに長たらしいコードが必要なんて「もう、ダメダメ」って感じの人もいるんじゃ
ないでしょうか。
2 コード
;システムクロック表示、設定プログラム ver0.1.1 ;COPYRIGHTS TSUYOSHI KASAI 1999 code segment assume cs:code,ds:code,es:code,ss:code ORG 100H START: ;スタート画面の表示 MOV AH,09H MOV DX,OFFSET DATA INT 21H START1: ;キー入力待ち MOV AH, 06H ;AH=6、DL=FFH キーボード入力、内部ループ無し MOV DL, 0FFH INT 21H JZ START1 ;キー入力なければSTART1に戻る START2: ;1..表示 2..時間設定 3..終了 押されたKEYに従って分岐 CMP AL, '1' JZ TIMEREAD ;時間表示ルーチンへ CMP AL, '2' JZ TIMESETK ;時間設定ルーチンへ CMP AL, '3' JZ EXITK ;終了へ JMP START ;それ以外のキーならSTARTへ TIMESETK: ;時間設定と終了ルーチンはショートジャンプでは届かないので、ジャンプし直し JMP TIMESET EXITK: JMP EXIT TIMEREAD: ;時間表示(年月日) MOV AH,2AH ;システムクロック読み込み INT 21H MOV YEAR, CX MOV MONTH,DH MOV DATE, DL MOV CL,0 MOV AX,1000 ;年を16進から10進に変換し、さらにアスキーコードにして表示 MOV DX,YEAR CALL COUNT ADD CL,30H MOV Y1000,CL MOV CL,0 MOV AX,100 CALL COUNT ADD CL,30H MOV Y100,CL MOV CL,0 MOV AX,10 CALL COUNT ADD CL,30H MOV Y10,CL ADD DL,30H MOV Y1,DL MOV CL,0 MOV DH,0 MOV DL,MONTH ;月をアスキーコードに変換し表示 MOV AX,10 CALL COUNT ADD CL, 30H MOV M10,CL ADD DL,30H MOV M1,DL MOV CL,0 MOV DL, DATE ;日をアスキーコードに変換し表示 MOV AX,10 CALL COUNT ADD CL, 30H MOV D10,CL ADD DL,30H MOV D1,DL MOV AH,9 MOV DX,OFFSET Y1000 INT 21H SECONDREAD: ;時間表示(時分秒) MOV AH,2CH INT 21H MOV TIME, CH MOV MINUTE, CL MOV SECOND, DH MOV CL,0 MOV AX,10 MOV DH,0 MOV DL,TIME CALL COUNT ADD CL,30H MOV T10, CL ADD DL,30H MOV T1,DL MOV CL,0 MOV DL,MINUTE CALL COUNT ADD CL,30H MOV MN10, CL ADD DL,30H MOV MN1,DL MOV CL,0 MOV DL,SECOND CALL COUNT ADD CL,30H MOV S10,CL ADD DL,30H MOV S1,DL MOV AH,9 MOV DX,OFFSET T10 INT 21H MOV AH,6 ;キーボード入力 MOV DL,0FFH INT 21H JZ SECONDREAD ;何かキー入力あればSTARTにもどる。なければ時間の表示を続行 MOV AH, 2 MOV DL, 0AH INT 21H JMP START TIMESET: ;時間の設定 MOV AH,9 MOV DX, OFFSET YEARSET INT 21H MOV AX, 0C0AH ;AX=0C0AH バッファを空にしてから、バッファに文字列入力 MOV DX, OFFSET YEARBUF ;年の入力 INT 21H MOV AH,2 MOV DL,0AH INT 21H MOV AL, YEARBUF[2] ;年(アスキー文字列)を16進数に変換する MOV BX, 1000 CALL SETCALC MOV YEAR, AX MOV AL, YEARBUF[3] MOV BX,100 CALL SETCALC ADD YEAR,AX MOV AL, YEARBUF[4] MOV BX,10 CALL SETCALC ADD YEAR, AX SUB YEARBUF[5], 30H MOV DL,YEARBUF[5] MOV DH,0 ADD YEAR, DX MOV AH,9 MOV DX,OFFSET MONTHSET INT 21H MOV AX, 0C0AH ;月の入力 MOV DX, OFFSET MONTHBUF INT 21H MOV AH,2 MOV DL, 0AH INT 21H MOV AL, MONTHBUF[2] MOV BX,10 CALL SETCALC MOV MONTH, AL SUB MONTHBUF[3],30H MOV DL,MONTHBUF[3] ADD MONTH, DL MOV AH,9 MOV DX, OFFSET DATESET INT 21H MOV AX,0C0AH ;日の入力 MOV DX, OFFSET DATEBUF INT 21H MOV AH, 2 MOV DL,0AH INT 21H MOV AL,DATEBUF[2] MOV BX, 10 CALL SETCALC MOV DATE, AL SUB DATEBUF[3], 30H MOV DL,DATEBUF[3] ADD DATE, DL MOV AH, 2BH ;AH=2BH 日付のセット MOV CX, YEAR MOV DH,MONTH MOV DL, DATE INT 21H CMP AL,0 JZ TIMESET1 MOV AH, 9 MOV DX, OFFSET FAIL1 INT 21H JMP START TIMESET1: ; 時刻をセットする MOV AH,9 MOV DX, OFFSET TIMESETW INT 21H MOV AX,0C0AH MOV DX, OFFSET TIMEBUF INT 21H MOV AH,2 MOV DL, 0AH INT 21H MOV AL,TIMEBUF[2] MOV BX, 10 CALL SETCALC MOV TIME, AL SUB TIMEBUF[3], 30H MOV DL,TIMEBUF[3] ADD TIME, DL MOV AH,9 MOV DX, OFFSET MINUTESET INT 21H MOV AX,0C0AH MOV DX, OFFSET MINUTEBUF INT 21H MOV AH,2 MOV DL,0AH INT 21H MOV AL,MINUTEBUF[2] MOV BX, 10 CALL SETCALC MOV MINUTE, AL SUB MINUTEBUF[3], 30H MOV DL,MINUTEBUF[3] ADD MINUTE, DL MOV AH,9 MOV DX, OFFSET SECONDSET INT 21H MOV AX,0C0AH MOV DX, OFFSET SECONDBUF INT 21H MOV AH,2 MOV DL,0AH INT 21H MOV AL,SECONDBUF[2] MOV BX, 10 CALL SETCALC MOV SECOND, AL SUB SECONDBUF[3], 30H MOV DL,SECONDBUF[3] ADD SECOND, DL MOV AH, 2DH MOV CH, TIME MOV CL,MINUTE MOV DH,SECOND MOV DL,0 INT 21H CMP AL, 0 JZ SETFINISH MOV AH,9 MOV DX, OFFSET FAIL1 INT 21H JMP START SETFINISH: MOV AH,9 MOV DX, OFFSET SETFINISHW INT 21H JMP START EXIT: ;終了 INT 20H SETCALC: ;アスキーコードを数値に変換 MOV AH,0 SUB AX, 30H MUL BX RET COUNT: ;それぞれの位(1の位、10の位・・1000の位)がいくつかをカウントする CMP DX,AX JB COUNTEND INC CL ;CL 各位の数値のカウント用 SUB DX,AX JMP COUNT COUNTEND: RET DATA DB 'COMPUTER SYSTEM CLOCK ver0.11',0DH,0AH,'<1--システムクロック ヒョウジ 2--システムクロックセット 3--END>',0DH,0AH DB '制作 Tsuyoshi KASAI',0DH,0AH,'$' YEAR DW ? ;表示用のデータ MONTH DB ? DATE DB ? TIME DB ? MINUTE DB ? SECOND DB ? Y1000 DB ? ;Y1000 年の1000の位 Y100 DB ? Y10 DB ? Y1 DB ? YY DB '/' M10 DB ? M1 DB ? MMT DB '/' D10 DB ? D1 DB ? DP DB 0DH,0AH,'$' T10 DB ? T1 DB ? TT DB ':' MN10 DB ? MN1 DB ? MM DB ':' S10 DB ? S1 DB ? SDATA DB 0DH, '$' YEARSET DB 'SYSTEM CLOCK SET (1ケタノスウジハ 01,02,03ノヨウニニュウリョクシテクダサイ)',0dh,0AH,'YEAR(1980-2079)--','$' MONTHSET DB 'MONTH(01-12)--','$' DATESET DB 'DATE(01-31)--','$' TIMESETW DB 'TIME(00-23)--','$' MINUTESET DB 'MINUTE(00-59)--','$' SECONDSET DB 'SECOND(00-59)--','$' YEARBUF DB 5,0,5 DUP(?) ;設定用のデータ入力用バッファ MONTHBUF DB 3,0,3 DUP(?) DATEBUF DB 3,0,3 DUP(?) TIMEBUF DB 3,0,3 DUP(?) MINUTEBUF DB 3,0,3 DUP(?) SECONDBUF DB 3,0,3 DUP(?) FAIL1 DB 'FAILED スウチガムコウデス',0DH,0AH,'$' SETFINISHW DB 'セットカンリョウ',0DH,0AH,'$' CODE ENDS END START |
実行画面の様子。
C:\newgame\ASM>clocka COMPUTER SYSTEM CLOCK ver0.11 <1--システムクロック ヒョウジ 2--システムクロックセット 3--END> 制作 Tsuyoshi KASAI 2001/05/02 23:36:24 |
コードは長たらしくて、ダメダメ感満点ですが、やってることは単純なので、じっくり見ればすぐ理解できる
と思います。